home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Gold Medal Software 3
/
Gold Medal Software - Volume 3 (Gold Medal) (1994).iso
/
prog
/
unld8616.arj
/
UNLOAD86.A86
< prev
next >
Wrap
Text File
|
1994-04-01
|
27KB
|
829 lines
;************************************************************************
;* *
;* UNLOAD86.A86 This is a MS-DOS unload program. See the help *
;* screen at the end of this file for details on its use. *
;* Written by: Mark D. Pickerill 9 Aug. 1988 *
;* Assemble with the 2500 A.D. X8086 assembler. *
;* *
;************************************************************************
;
CR: EQU 0DH ; Carriage return
LF: EQU 0AH ; Line feed
EOF: EQU 1AH ; End of file
;
ASSUME CS:NOTHING,DS:NOTHING,ES:NOTHING
;
CHIP 8086 ; 8086 mode
;
ORG 0100H ; Start of tpa
;
UNLOAD: JMP SHORT START ; Skip data area
;
FILDAT: ;
DB 0FFH ; Data to fill empty space in rom (if selected)
BNPFTYP: ;
DB 'PN' ; Pn for bnpf, hl for bhlf, or 10 for b10f
FTYPE: ;
DB '.HEX',00H ; File type
FTYPE1: ;
DB '.BNP',00H ; File type for bnpf files
DOEOF: ;
DB 00H ; Zero for no eof (cntrl-z, 1ah) on end of file
; End of user patchable options
NUMTERM: ; 0 means UNIX style LF only termination
DB 02H ; 1 means TRS-80/MAC CR only termination
ACR: ; 2 means standard MS-DOS or CP/M CRLF term.
DB 0DH ; The first terminator
ALF: ;
DB 0AH ; The second...
OUTTYPE: ;
DB 00H ; 00 for hex, non-zero for bnpf
USELIN: ;
DB 00H ; 00 for no extended linear address
USEEXT: ;
DB 00H ; 00 for no extended address records
DOFILL: ;
DB 00H ; 00 not to fill to end of rom
OVERRIDE: ;
DB 00H ; Ff if overriding forced extended addressing
ENDSEG: ;
DW 0000H ; Space to store end segment for rom fill
ENDADDR: ;
DW 0000H ; Space to store end address for rom fill
OOD: ;
DB 00H ; Flag 0 for read from disk, ff to use fildat
RAWHEX: ;
DB 00H ; For straight ASCII hex...
;
NOPARMS:JMP HELP ; Extend short jump
;
START: PUSH CS ; Set data segment
POP DS ; It's set
PUSH DS ; Get this segment
POP ES ; And set es as well
CALL ILPRT ; Print signon message
DB CR,LF,'UNLOAD86 ver. 1.6',00H
;
MOV SI,0080H ; Point to parameter field in psp
LODSB ; Get parameter length
MOV CL,AL ; Into cl
OR CL,CL ; Force flags
JZ NOPARMS ; Print help screen
MOV CH,00H ; Zero ch
LOOP1: LODSB ; Get byte from parameter field
CMP AL,' ' ; Space?
LOOPZ LOOP1 ; Wait until you get a non-space char
JZ NOPARMS ; Just spaces, print help screen
CMP AL,'/' ; Switch char?
JZ NOPARMS ; No filename!, print help screen
CMP AL,'-' ; Alt switch for unix types
JZ NOPARMS ; No filename!, print help screen
CMP AL,'[' ; Alt switch for cp/m types
JZ NOPARMS ; No filename!, print help screen
LEA DI,INFN ; Point to input filename area
STOSB ; Stuff this char
LOOP2: LODSB ; Get byte
CMP AL,' ' ; Space?
JZ NOSP ; Yes,ignore
CMP AL,'/' ; Or switch char?
JZ SWITCH ; Yes
CMP AL,'-' ; Alt switch for unix types
JZ SWITCH ; Yes
CMP AL,'[' ; Alt switch for cp/m types
JZ SWITCH ; Yes
STOSB ; Stuff char
NOSP: LOOP LOOP2 ; Nope
JMP CONT ; No more
SWITCH: LODSB ; Get switch options
AND AL,5FH ; Make upper case as ibm types
; Usualy use lower case!
CMP AL,'B' ; Bnpf option?
JZ SETBNPF ; Yes
CMP AL,'O' ; Override forced extended address records?
JZ SETOVR ; Yes
CMP AL,'E' ; Use extended addressing?
JZ SETEXT ; Yes
CMP AL,'P' ; Set eprom type?
JZ SETROM ; Yes
CMP AL,'L' ; Use extended linear addressing?
JZ SETLIN ; Yes
CMP AL,'Z' ; Put control-z at end of file?
JZ SETEOF ; Yes
CMP AL,'H' ; Do raw hex?
JZ SETRAW ; Yes
CMP AL,'T' ; CR only type output?
JZ SETCR ; Yes
CMP AL,'U' ; LF only type output?
JZ SETLF ; Yes
LOOP SWITCH ; Look for more options
JMP CONT ; No more
;
SETOVR: XOR AL,AL ; Turn off extended addressing
MOV [USEEXT],AL ; Do it
MOV [USELIN],AL ; Turn off extended linear addressing
DEC AL ; Indicate override of extended addressing
MOV [OVERRIDE],AL ; Flag it as such
LOOP SWITCH ; Look for more options
JMP CONT ; No more
;
SETEXT: XOR AL,AL ; Turn off extended linear addressing
MOV [USELIN],AL ; Do it
DEC AL ; Indicate use of extended addressing
MOV [USEEXT],AL ; Flag it as such
LOOP SWITCH ; Look for more options
JMP CONT ; No more
;
SETLIN: XOR AL,AL ; Turn off extended addressing
MOV [USEEXT],AL ; Do it
MOV [DOFILL],AL ; Turn off fill to end of rom
DEC AL ; Get an ff
MOV [OVERRIDE],AL ; Flag extended override
MOV [USELIN],AL ; Flag use of extended linear addressing
LOOP SWITCH ; Look for more options
JMP CONT ; No more options
;
SETBNPF:NOT BYTE PTR [OUTTYPE] ; Indicate bnpf option
JMP SHORT LOOKMOR ; Look for more options
;
SETEOF: NOT BYTE PTR [DOEOF] ; Put eof at end of file
;
LOOKMOR:LOOP SWITCH ; If more, look for additional options
JMP CONT ; No more
;
SETRAW: MOV [RAWHEX],BYTE PTR 0FFH ; Turn on raw hex option
JMP SHORT LOOKMOR ; And look for more options
;
SETLF: MOV [NUMTERM],BYTE PTR 00H ; Setup for UNIX LF only
JMP SHORT LOOKMOR ; And look for more
;
SETCR: MOV [NUMTERM],BYTE PTR 01H ; Setup for TRS-80/MACintosh CR only
JMP SHORT LOOKMOR ; Go look for more options
;
SETROM: MOV [USELIN],BYTE PTR 00H ; Turn off linear extended addressing
DEC CX ; Decrement loop counter
LODSB ; Get char
CMP AL,'0' ; At least a zero?
JC LOOKMOR ; No,ignore
CMP AL,'A' ; At least an a?
JC NUM ; Numeric
AND AL,5FH ; Force upper case
CMP AL,'G' ; More garbage?
JNC LOOKMOR ; Yes, ignore
SUB AL,37H ; Remove alpha bias
JMP SHORT FOUNDIT ; And continue
NUM: CMP AL,3AH ; Above numeric?
JNC LOOKMOR ; Yes, ignore
SUB AL,30H ; Remove numeric bias
FOUNDIT:CMP AL,0CH ; Big rom?
JC SMALL ; No
CALL CHKOVR ; Unless user has overridden
SMALL: PUSH SI ; Save pointer
LEA SI,ATABLE ; Point to address table
ADD AL,AL ; Multiply by two
ADD AL,AL ; And by four
XOR AH,AH ; Clear ah
ADD SI,AX ; Add in offset
LODSW ; Get segment address
MOV [ENDSEG],AX ; Stuff it
LODSW ; Get offset address
MOV [ENDADDR],AX ; Stuff it
MOV [DOFILL],BYTE PTR 0FFH ; Flag fillrom operation
POP SI ; Restore si
JMP LOOKMOR ; Go look for more options
;
CONT: MOV [DI],BYTE PTR 00H ; Terminate string
LEA SI,INFN ; Copy input to output fn
LEA DI,OUTFN ; Pointing to output filename
MOV CX,60D ; 64-4 for 'hex0' is 60
LOOP3: LODSB ; Get byte
STOSB ; Stash it (need it in al, movsb won't work)
CMP AL,'.' ; Looking for that file extension
JZ DONE ; Found the dot
CMP AL,00H ; End?
LOOPNZ LOOP3 ; Continue
DONE: DEC DI ; Backup over dot or zero
MOV CX,0005H ; Five bytes to move
MOV AL,[OUTTYPE] ; Hex or bnpf?
OR AL,AL ; Force flags
JZ OHEX ; Hex
LEA SI,FTYPE1 ; Point to file type for bnpf
JMP SHORT ALL ; And continue
OHEX: LEA SI,FTYPE ; Point to file type for hex
ALL: REP MOVSB ; Move the rest
;
MOV AL,00H ; Read access code
MOV AH,3DH ; Open file function
LEA DX,INFN ; Point to input file name
INT 21H ; Open the file
MOV [INHDL],AX ; Save handle
JNC OK ; Ok
CALL ILPRT ; Print this...
DB CR,LF,'Failure to Open Input file',00H
JMP FINIS ; Go to error handler
;
OK: CMP [NUMTERM],BYTE PTR 00H ; Unix configuration?
JNZ TERMOK ; No, it's OK
MOV [NUMTERM],BYTE PTR 01H ; Force to 1...
MOV AL,[ALF] ; Get LF
MOV [ACR],AL ; And make 00 mean LF termination...
MOV [CNTRLB+1],AL ; And fix BNPF start sequence
MOV [CNTRLC+1],AL ; And fix BNPF end sequence
MOV [EOFREC+11D],AL ; Fix hex EOF record
;
TERMOK: CMP CS:[RAWHEX],BYTE PTR 00H ; Check for raw hex
JZ OKK ; Not raw hex
XOR AL,AL ; A zero
MOV [USELIN],AL ; Turn off linear records
MOV [USEEXT],AL ; And extended records
MOV [DOFILL],AL ; No fill to end
MOV [OVERRIDE],AL ; No override of extended recs, meaningless
;
OKK: MOV BX,AX ; Handle in bx
MOV AX,4202H ; Move to end of file
XOR CX,CX ; Clear offsets
MOV DX,CX ; Including dx
INT 21H ; Do it
OR DX,DX ; Longer than 64k?
JZ LT64K ; No
CALL CHKOVR ; Check extended addressing override
;
LT64K: XOR CX,CX ; Clear offsets
MOV DX,CX ; All 32 bits
MOV AX,4200H ; Move back to start of file
MOV BX,[INHDL] ; Get handle
INT 21H ; Moved back
MOV CL,00H ; Normal addributes
MOV AH,3CH ; Create file function
LEA DX,OUTFN ; Point to file name
INT 21H ; Open the file
JNC OK1 ; Ok
CALL ILPRT ; Print this...
DB CR,LF,'Failure to Open output file',00H
JMP FINIS ; Go to error handler
OK1: MOV [OUTHDL],AX ; Save handle
MOV AL,[OUTTYPE] ; Get output format
OR AL,AL ; Force flags
JZ READ ; Don't do start char for bnpf
LEA DX,CNTRLB ; Point to start byte
MOV CL,[NUMTERM] ; Get number of termination characters...
XOR CH,CH ; Zero upper
INC CX ; To conpensate for cntrl-b!
CALL DSKWRT ; Write it
JNC READ ; Ok
JMP BADWR ; Error
;
READ: LEA DI,INBUF ; Point to input buffer
MOV CX,16D ; Fill entire buffer
MOV AL,[FILDAT] ; Get fill data
MOV AH,AL ; Dup into ah
REP STOSW ; Do it
;
MOV AL,[OOD] ; Already out of data?
OR AL,AL ; Force flags
JNZ FILLIT ; Yup
LEA DX,INBUF ; Point to buffer
MOV BX,[INHDL] ; Get handle
CALL DSKRD ; Go get data
JNC ROK ; Ok
CALL ILPRT ; Print this...
DB CR,LF,'Error Reading Input file',00H
JMP FINIS ; Go to error handler
;
CNTRLB: ;
DB 02H,CR,LF ; Bnpf start
;
ROK: OR AX,AX ; Completely finished?
JNZ NOPE ; Nope
MOV AL,[OUTTYPE] ; Check for bnpf
OR AL,AL ; Force flags
JNZ EXIT ; Bnpf ignores all this...
MOV AL,0FFH ; Indicate we're finished reading from disk
MOV [OOD],AL ; Flag it
MOV AL,[DOFILL] ; Check for fillrom function
OR AL,AL ; Force flags
JZ EXIT ; Not selected
FILLIT: MOV AX,[EXTEND] ; Get current segment
SUB AX,1000H ; Compensate to what is in use
CMP [ENDSEG],AX ; Check against selected end segment
JC TOOBIG ; Warn operator that his data won't fit
JNZ NOPE ; Segment hasn't been reached yet, continue
MOV AX,[ADDRESS] ; Get current address
DEC AX ; To last location, not next avail loc
CMP [ENDADDR],AX ; Check against selected end address
JC TOOBIG ; Warn operator that his data won't fit
JNZ NOPE ; Address hasn't been reached yet
;
EXIT: JMP FINISHUP ; Yes, finish up & terminate
TOOBIG: JMP WARN ; Tell operator
NOPE: MOV AL,[OUTTYPE] ; Get output format
OR AL,AL ; Force flags
JZ HEX ; Do hex
; Drop through to bnpf
LEA SI,INBUF ; Point to input buffer
MOV CX,32D ; 32 bytes to process
BNPF: LEA DI,OUTBUF ; Output buffer
MOV [DI],BYTE PTR 'B' ; The b for begin
INC DI ; Next location
BIGLP: LODSB ; Get byte
PUSH CX ; Save byte loop
MOV CX,0008H ; 8 bits in a byte
BNPFLP: RCL AL,1 ; Rotate through carry
JC P ; High
MOV AH,[BNPFTYP+1] ; Get the byte for low
MOV [DI],AH ; Put in buffer
INC DI ; Next location
LOOP BNPFLP ; Do entire byte
JMP ONEBYTE ; Complete & write
P: MOV AH,[BNPFTYP] ; Get the byte for high
MOV [DI],AH ; Put in buffer
INC DI ; Next location
LOOP BNPFLP ; Do entire byte
ONEBYTE:MOV [DI],BYTE PTR 'F' ; The f for finish
POP CX ; Recover byte loop
INC DI ; Next dest
;
MOV AL,[ACR] ; Get first terminator
STOSB ; Append it
MOV BP,11D ; Assume eleven bytes every time
CMP [NUMTERM],BYTE PTR 02H ; Two terminations?
JNZ SKIPLF1 ; No, skip
MOV AL,[ALF] ; Get second terminator
STOSB ; Append it
INC BP ; And write 12 bytes!
;
SKIPLF1:PUSH CX ; Save loop counter
PUSH SI ; Save input counter
MOV CX,BP ; Get number to write...
CALL WRITE ; Write byte
POP SI ; Recover input counter
POP CX ; Recover loop counter
LOOP BNPF ; Do next byte
JMP READ ; Read next 32 bytes
;
HEX: XOR BX,BX ; Output counter
MOV CX,32D ; Input counter
XOR DX,DX ; Dl is checksum reg
MOV AX,[ADDRESS] ; Get current load address
OR AX,AX ; Force flags
JNZ NOEXT ; No extended address record needed
CALL EAR ; Do extended addressing if selected
NOEXT: LEA SI,INBUF ; Point to input buffer
LEA DI,OUTBUF ; Point to output buffer
MOV AL,[RAWHEX] ; Check for raw hex
OR AL,AL ; Force flags
JNZ LOOP4 ; Raw hex does no colons, addresses, etc...
;
MOV [DI],BYTE PTR ':' ; Stuff that colon
INC DI ; And point to next
INC BX ; And increment counter
MOV AL,20H ; All are 32 byte records
CALL BITE ; Stuff it
MOV AX,[ADDRESS] ; Get load address
XCHG AL,AH ; Do high byte first
CALL BITE ; Send it
XCHG AH,AL ; Now do low byte
CALL BITE ; Send it
MOV AX,[ADDRESS] ; Get load address
ADD AX,20H ; Increment to next
MOV [ADDRESS],AX ; Put back
MOV AL,00H ; Record type 00
CALL BITE ; Send it
LOOP4: LODSB ; Get input
CALL BITE ; Process
LOOP LOOP4 ; Until done
MOV AL,DL ; Get checksum
CMP CS:[RAWHEX],BYTE PTR 00H ; Check for raw hex...
JNZ SKIPCS ; Raw hex does no checksums either...
;
CALL BITE ; Process, [clobbering dl]
SKIPCS: MOV AL,[ACR] ; Get first terminator
STOSB ; Append it
INC BX ; Bump output counter appropiately
CMP [NUMTERM],BYTE PTR 02H ; Two terminations?
JNZ SKIPLF ; No, skip
MOV AL,[ALF] ; Get second terminator
STOSB ; Append it
INC BX ; Bump output counter appropiately
;
SKIPLF: MOV CX,BX ; Get count into cx
CALL WRITE ; Write output
JMP READ ; Read more
;
WRITE: LEA DX,OUTBUF ; Point to beginning of output buffer
MOV BX,[OUTHDL] ; Get output handle
CALL DSKWRT ; Write data
JNC WOK ; Ok
BADWR: CALL ILPRT ; Print this...
DB CR,LF,'Error Writing Output file',00H
JMP FINIS ; Go to error handler
WOK: RET ; Near
;
EAR: PUSH AX ; Save everything
MOV AL,[USEEXT] ; Get extended address flag
OR AL,[USELIN] ; Or in extended linear flag
JNZ GOAHEAD ; If either set, go do it!
;
MOV AX,[EXTEND] ; Get extended address anyway
ADD AX,1000H ; Increment to next 64k block
MOV [EXTEND],AX ; Put back for consistancy
POP AX ; Restore ax
RET ; Go home
;
GOAHEAD:PUSH DI ;
PUSH CX ;
PUSH DX ;
PUSH SI ;
PUSH BX ;
LEA DI,OUTBUF ; Point to output buffer
MOV [DI],BYTE PTR ':' ; Stuff that colon
INC DI ; And point to next
INC BX ; And increment counter
MOV AL,02H ; Two bytes of data in extended record
CALL BITE ; Stuff it
MOV AX,0000H ; Extended address records have load addr of 0
XCHG AL,AH ; Do high byte first
CALL BITE ; Send it
XCHG AH,AL ; Now do low byte
CALL BITE ; Send it
CMP BYTE PTR [USELIN],0FFH ; Extended linear addressing?
JNZ DOEXTS ; Yes
MOV AL,04H ; Record type 04 extended linear addressing
JMP SHORT BOTH ; Continue
;
DOEXTS: MOV AL,02H ; Record type 02 extended addressing
BOTH: CALL BITE ; Send it
MOV AX,[EXTEND] ; Get current extended address
XCHG AL,AH ; Do high byte first
CALL BITE ; Send it
XCHG AH,AL ; Now do low byte
CALL BITE ; Send it
CMP BYTE PTR [USELIN],0FFH ; Extended linear addressing
JNZ DOEXTSS ; Yes
ADD WORD PTR [EXTEND],0001H ; Bump to next block
JMP SHORT BOTH1 ; Continue
;
DOEXTSS:ADD WORD PTR [EXTEND],1000H ; Bump to next segment
BOTH1: MOV AL,DL ; Get checksum
CALL BITE ; Process, [clobbering dl]
MOV AL,[ACR] ; Get first terminator
STOSB ; Append it
INC BX ; Bump output counter appropiately
CMP [NUMTERM],BYTE PTR 02H ; Two terminations?
JNZ SKIPLF2 ; No, skip
MOV AL,[ALF] ; Get second terminator
STOSB ; Append it
INC BX ; Bump output counter appropiately
;
SKIPLF2:MOV CX,BX ; Get count into cx
CALL WRITE ; Write output
POP BX ; Recover everything
POP SI ;
POP DX ;
POP CX ;
POP DI ;
POP AX ;
RET ; Go home
;
CHKOVR: PUSH AX ; Save ax
MOV AL,[OVERRIDE] ; Check to see if extended override selected
OR AL,AL ; Force flags
JNZ OVR ; Overridden by user
MOV AL,0FFH ; Otherwise flag extended addressing
MOV [USEEXT],AL ; Flagged
OVR: POP AX ; Restore ax
RET ; Go home
;
FINISHUP: ;
MOV AH,2CH ; Get time function
INT 21H ; Go get it
MOV AL,DL ; Get hundreths of seconds
OR AL,AL ; Force flags
JPO SKIP ; Don't display
CALL ILPRT ; Print...
DB CR,LF,'Dedicated to the Goddess Athena!',00H
;
SKIP: CALL ILPRT ; Print this...
DB CR,LF,'Function Complete.',CR,LF,00H
MOV AL,[OUTTYPE] ; Get output format
OR AL,AL ; Force flags
JZ HEXEND ; Do hex
; Drop through to bnpf
;
BNPFEND:LEA DX,CNTRLC ; Point to eof marker
MOV CL,[NUMTERM] ; Get number of termination characters...
XOR CH,CH ; Zero upper
INC CX ; To compensate for the cntrl-c!
CALL DSKWRT ; Write it
JNC WOKK ; Ok
JMP BADWR ; Error
;
WARN: CALL ILPRT ; Print this...
DB CR,LF,LF,'WARNING: Input data file too large for output size'
DB ' selected.',07H,LF,00H ;
JMP FINISHUP ; Terminate
;
CNTRLC: ;
DB 03H,CR,LF ; Termination for bnpf
;
HEXEND: MOV AL,[RAWHEX] ; Check for raw hex
OR AL,AL ; Force flags
JNZ WOKK ; Raw hex does no end of file record either...
;
LEA DX,EOFREC ; Point to eof record
MOV CX,000BH ; Eleven bytes
ADD CL,BYTE PTR [NUMTERM] ; Add in number of line terminations...
CALL DSKWRT ; Write it
JNC WOKK ; Ok
JMP BADWR ; Error
;
ENDOF: ;
DB 1AH ; End of file mark
;
WOKK: MOV AL,[DOEOF] ; Do we want a ctrl-z?
OR AL,AL ; Force flags
JZ NOEOF ; No eof
LEA DX,ENDOF ; Point to eof
MOV CX,0001H ; One byte
CALL DSKWRT ; Write it
;
NOEOF: CALL FLUSH ; Force disk write
MOV AH,3EH ; Close the file now
MOV BX,[OUTHDL] ; Close output
INT 21H ; Close the damn thing
JNC CLOK ; Closed ok
CALL ILPRT ; Print this...
DB CR,LF,'Error Closing Output file!',00H
;
CLOK: MOV AH,3EH ; Close the file now
MOV BX,[INHDL] ; Close input
INT 21H ; Close the damn thing
JNC FINISH ; Closed ok
CALL ILPRT ; Print this...
DB CR,LF,'Error Closing Input file!',00H
;
FINISH: MOV AX,4C00H ; No-error termination
INT 21H ; Bye-bye
;
FINIS: MOV AX,4CFFH ; Error termination
INT 21H ; Bye-bye
;
EOFREC: ;
DB ':00000001FF',CR,LF ; End of file record
;
;************************************************************************
;* *
;* ILPRT: This is an 8088 in-line print routine. It will print *
;* the string following the CALL NEAR instruction until a 00H is *
;* encountered. Accepts: Data string to print in memory following*
;* the CALL NEAR used to invoke this routine. Returns: Nothing. *
;* Calls: CONOUT. Clobbers: ES,SI *
;* *
;************************************************************************
;
ILPRT: PUSH CS ; Get code segment
POP ES ; Into es
POP SI ; Get offset
PUSH AX ; Save ax
PUSH DX ; And dx
ILLP: LODSB ; Get char
OR AL,AL ; Force flags
JZ ILEXIT ; Exit if last
CALL CONOUT ; Send char
JMP SHORT ILLP ; Loop til done
ILEXIT: POP DX ; Restore dx
POP AX ; And ax
PUSH SI ; And return offset
RET ; Near
;
CONOUT: MOV AH,02H ; Conout call
MOV DL,AL ; Get char
INT 21H ; Do it
RET ; Near
;
BITE: SUB DL,AL ; Generate checksum
PUSH AX ; Save
AND AL,0F0H ; Mask out lower nybble
ROR AL,1 ; Get msn into lower nybble
ROR AL,1 ; (8088 compatibility sucks...)
ROR AL,1 ;
ROR AL,1 ; Now it's there
CALL NYB ; Process nybble
MOV [DI],AL ; Save in disk buffer
INC BX ; Increment count
INC DI ; Next location in buffer
POP AX ; Recover byte
AND AL,0FH ; Mask lsn
CALL NYB ; Process nybble
MOV [DI],AL ; Save in disk buffer
INC BX ; Increment count
INC DI ; Next location in buffer
RET ; Near
;
; Converts lower nybble in al to ascii hex
NYB: CMP AL,0AH ; Letter?
JNC NYB1 ; Yes
ADD AL,30H ; Add in numeric bias
RET ; Go home (near)
NYB1: ADD AL,37H ; Add in letter bias
RET ; Go home (near)
;
;************************************************************************
;* *
;* DSKWRT: This routine implements a double buffer disk write. *
;* It accepts the write request and blocks larger writes to *
;* the disk for increased performance. Accepts: Pointer to ouput *
;* data in DX, byte count in CX. Returns: Status in carry flag, *
;* carry set if error. Clobbers: CX,AX,SI,DI. Calls: INT 21 *
;* *
;************************************************************************
;
DSKWRT: MOV SI,DX ; Get data pointer in si
LEA DI,REALOUT ; Point to output buffer
ADD DI,WORD PTR [OUTPTR] ; Point to 1st free location
PUSH CX ; Save byte count
REP MOVSB ; Move the data
POP CX ; Get the byte count back
ADD [OUTPTR],CX ; Bump up counter/pointer
MOV AX,[OUTPTR] ; Get it
CMP AX,16384D ; Have we used at least 16k?
JGE FLUSH ; Yes we have, flush output buffer to disk
CLC ; Everyone's ok
RET ; Not yet
;
FLUSH: LEA DX,REALOUT ; Point to beginning of output buffer
MOV BX,[OUTHDL] ; Get output handle
MOV AH,40H ; Write function
MOV CX,[OUTPTR] ; Get output count
OR CX,CX ; Anything there?
JZ NOFLUSH ; Nope, don't bother
INT 21H ; Do it
PUSHF ; Save status
XOR AX,AX ; A zero
MOV [OUTPTR],AX ; Re-init output pointer/counter
POPF ; Recover status
NOFLUSH:RET ; Go home
;
;************************************************************************
;* *
;* DSKRD: This routine implements a double buffer disk read. *
;* It accepts the 32 byte read request and deblocks larger *
;* reads from the disk for increased performance. Accepts: *
;* Place to stuff this stuff in DX. Returns: Status in *
;* carry flag, carry set if error, Number of bytes returned in AX. *
;* This number will only be smaller than 32 at the end of the *
;* input file. Clobbers: CX,AX,SI,DI. Calls: INT 21 *
;* *
;************************************************************************
;
DSKRD: MOV DI,DX ; Get destination
LEA SI,REALIN ; Point to input buffer
ADD SI,WORD PTR [INPTR] ; Add in pointer
MOV CX,[INCNT] ; Get number of bytes left
OR CX,CX ; Force flags
JZ RD ; Outta data here, go get more from disk
CMP CX,32D ; How many?
JL LAST ; Last time through
MOV CX,32D ; Xfer 32 bytes
REP MOVSB ; Move bytes into program's input buffer
MOV AX,32D ; We moved 32 bytes
ADD [INPTR],AX ; Bump up input pointer
SUB [INCNT],AX ; Bump down input count
CLC ; Clear carry
RET ; Go home
;
LAST: REP MOVSB ; Move bytes into program's input buffer
MOV AX,[INCNT] ; Last number of bytes moved
XOR CX,CX ; A zero
MOV [INCNT],CX ; No more avail
MOV [INPTR],CX ; Zero pointer
CLC ; Clear carry
RET ; Go home
;
RD: PUSH DX ; Save program's input pointer
LEA DX,REALIN ; Point to buffer
MOV CX,4096D ; Read another 4k bytes
MOV BX,[INHDL] ; Get handle
MOV AH,3FH ; Read function
INT 21H ; Do it
POP DX ; Recover program's input pointer
JNC RD1 ; If error, return immediately
RET ; Go away
;
RD1: XOR CX,CX ; Get a zero
MOV [INPTR],CX ; Zero input pointer
MOV [INCNT],AX ; Init number of bytes avail
OR AX,AX ; Force flags
JNZ DSKRD ; Recursively re-enter routine if any data
RET ; No data, program will handle...
;
INHDL: ;
BLKB 2 ; Storage for input file handle
OUTHDL: ;
BLKB 2 ; Storage for output file handle
ADDRESS: ;
DW 0000H ; Current address
EXTEND: ;
DW 0000H ; Current extended address
OUTPTR: ;
DW 0000H ; Output pointer
INPTR: ;
DW 0000H ; Input buffer pointer
INCNT: ;
DW 0000H ; Bytes left in buffer
INFN: EQU $ ; 64 bytes input filename storage
OUTFN: EQU INFN+64D ; Plenty of room for a filename & path
INBUF: EQU OUTFN+64D ; Thirty two byte input buffer
OUTBUF: EQU INBUF+32D ; 128 byte output buffer
REALIN: EQU OUTBUF+128D ; 4k 'real' input buffer
REALOUT:EQU REALIN+4096D ; All these buffers overlay the help file
;
HELP: ; Called only if nothing is going to happen
; Otherwise, this routine is overwritten
MOV AX,[BNPFTYP] ; Check for change to bnpf
CMP AX,'NP' ; Un-changed?
JZ YES ; Yes
MOV [BNPFPATCH],AX ; No, patch instructions
MOV [BNPFPTCH],AX ; Again
YES: LEA SI,FTYPE ; Point to hex filename
LEA DI,F ; Point to hex filename in instructions
MOV CX,0002H ; 2 words = 4 bytes
REP MOVSW ; Move them
;
LEA SI,FTYPE1 ; Point to bnpf filename
LEA DI,F1 ; Point to bnpf filename in instructions
MOV CX,0002H ; 2 words = 4 bytes
REP MOVSW ; Move them
JMP SHORT NEXT ; Self-modifying code, flush queu
NEXT: CALL ILPRT ; Print help screen
DB ', Binary --> Intel hex or Binary --> BNPF conversion.'
DB CR,LF,'Usage: UNLOAD86 FILENAME.TYP [/OPTIONS] '
DB CR,LF,'Where Options are:'
DB CR,LF,' B for B'
BNPFPTCH: ;
DB 'NPF instead of INTeL hex.'
DB CR,LF,' H for raw ASCII hex output'
DB CR,LF,' E to use extended addressing on files <=64K'
DB CR,LF,' L to use extended linear addressing'
DB CR,LF,' O to override forced extended addressing.'
DB CR,LF,' Z to place a Control-Z at end of file.'
DB CR,LF,' U for LF only UNIX style output'
DB CR,LF,' T for CR only TRS-80/MACintosh style output'
DB CR,LF,' P to fill output file to end of EPROM.'
DB CR,LF,' Uses the following subcommands:'
DB CR,LF,' 0 32 Bytes 1 64 Bytes'
DB CR,LF,' 2 128 Bytes 3 256 Bytes'
DB CR,LF,' 4 512 Bytes 5 1K Bytes'
DB CR,LF,' 6 2K Bytes 7 4K Bytes'
DB CR,LF,' 8 8K Bytes 9 16K Bytes'
DB CR,LF,' A 32K Bytes B 64K Bytes'
DB CR,LF,' C *128K Bytes D *256K Bytes'
DB CR,LF,' E *512K Bytes F *1Meg Bytes'
DB CR,LF,' * Forces extended addressing'
DB CR,LF,'INTeL hex output files are '
F: ; Self patch instructions
DB '.HEX' ;
DB ' B' ;
BNPFPATCH: ;
DB 'NP' ;
DB 'F output files are '
F1: ; Self patch instructions
DB '.BNP' ;
DB CR,LF,'Note: - or [ may be used instead of / for switches.',00H
JMP FINIS ; Terminate
;
ATABLE: ; Table of rom sizes for fillrom option
DW 0000H ; Segment for 32 byter
DW 001FH ; Address for 32 byter
DW 0000H ; Segment for 64 byter
DW 003FH ; Address for 64 byter
DW 0000H ; Segment for 128 byter
DW 007FH ; Address for 128 byter
DW 0000H ; Segment for 256 byter
DW 00FFH ; Address for 256 byter
DW 0000H ; Segment for 512 byter
DW 01FFH ; Address for 512 byter
DW 0000H ; Segment for 1k byter
DW 03FFH ; Address for 1k byter
DW 0000H ; Segment for 2k byter
DW 07FFH ; Address for 2k byter
DW 0000H ; Segment for 4k byter
DW 0FFFH ; Address for 4k byter
DW 0000H ; Segment for 8k byter
DW 1FFFH ; Address for 8k byter
DW 0000H ; Segment for 16k byter
DW 3FFFH ; Address for 16k byter
DW 0000H ; Segment for 32k byter
DW 7FFFH ; Address for 32k byter
DW 0000H ; Segment for 64k byter
DW 0FFFFH ; Address for 64k byter
DW 1000H ; Segment for 128k byter
DW 0FFFFH ; Address for 128k byter
DW 3000H ; Segment for 256k byter
DW 0FFFFH ; Address for 256k byter
DW 7000H ; Segment for 512k byter
DW 0FFFFH ; Address for 512k byter
DW 0F000H ; Segment for 1m byter
DW 0FFFFH ; Address for 1m byter
;
END ;